//v.2.6 build 100722
/*
Copyright DHTMLX LTD. http://www.dhtmlx.com
To use this component please contact sales@dhtmlx.com to obtain license
*/
function dataProcessor(serverProcessorURL)
{
	this.serverProcessor = serverProcessorURL;
	this.action_param="!nativeeditor_status";
	this.object = null;
	this.updatedRows = [];
	this.autoUpdate = true;
	this.updateMode = "cell";
	this._tMode="GET";
	this.post_delim = "_";
	this._waitMode=0;
	this._in_progress={};
	this._invalid={};
	this.mandatoryFields=[];
	this.messages=[];
	this.styles={updated:"font-weight:bold;",
 inserted:"font-weight:bold;",
 deleted:"text-decoration : line-through;",
 invalid:"background-color:FFE0E0;",
 invalid_cell:"border-bottom:2px solid red;",
 error:"color:red;",
 clear:"font-weight:normal;text-decoration:none;"
 };
	this.enableUTFencoding(true);
	dhtmlxEventable(this);
	return this;
};

dataProcessor.prototype=
{
	setTransactionMode:function(mode,total)
	{
		this._tMode=mode;
		this._tSend=total;
	},
	
	escape:function(data)
	{
		if (this._utf)
			return encodeURIComponent(data);
		else
			 return escape(data);
	},
 
	enableUTFencoding:function(mode){this._utf=convertStringToBoolean(mode);},
 
	setDataColumns:function(val){this._columns=(typeof val == "string")?val.split(","):val;},
 
	getSyncState:function(){return !this.updatedRows.length;},
 
	enableDataNames:function(mode){this._endnm=convertStringToBoolean(mode);},
 
	enablePartialDataSend:function(mode){this._changed=convertStringToBoolean(mode);},
 
 setUpdateMode:function(mode,dnd){this.autoUpdate = (mode=="cell");this.updateMode = mode;this.dnd=dnd;},
 ignore:function(code,master){this._silent_mode=true;code.call(master||window);this._silent_mode=false;},
 
 setUpdated:function(rowId,state,mode){if (this._silent_mode)return;
 
 var ind=this.findRow(rowId);
 mode=mode||"updated";
 var existing = this.obj.getUserData(rowId,this.action_param);
 
 if (existing && mode == "updated")
	 mode=existing;
 
 if (state)
 {
	 this.set_invalid(rowId,false);
	 this.updatedRows[ind]=rowId;
	 this.obj.setUserData(rowId,this.action_param,mode);
	 
	 if (this._in_progress[rowId])
		 this._in_progress[rowId]="wait";
  }else{
	 if (!this.is_invalid(rowId))
	 {
		 this.updatedRows.splice(ind,1);
		 this.obj.setUserData(rowId,this.action_param,"");
	 }
  };
  
  if (!state)
	  this._clearUpdateFlag(rowId);
  
  this.markRow(rowId,state,mode);
  
  if (state && this.autoUpdate)
	  this.sendData(rowId);
  },
 _clearUpdateFlag:function(id){},
 markRow:function(id,state,mode){var str="";var invalid=this.is_invalid(id);if (invalid){str=this.styles[invalid];state=true;};if (this.callEvent("onRowMark",[id,state,mode,invalid])){str=this.styles[state?mode:"clear"]+str;this.obj[this._methods[0]](id,str);if (invalid && invalid.details){str+=this.styles[invalid+"_cell"];for (var i=0;i < invalid.details.length;i++)if (invalid.details[i])this.obj[this._methods[1]](id,i,str);}}},
 getState:function(id){return this.obj.getUserData(id,this.action_param);},
 is_invalid:function(id){return this._invalid[id];},
 set_invalid:function(id,mode,details){if (details)mode={value:mode, details:details, toString:function(){return this.value.toString();}};this._invalid[id]=mode;},
 
 checkBeforeUpdate:function(rowId){return true;},
 
 sendData:function(rowId)
 {
	 //alert('Aqui');
	 if (this._waitMode && (this.obj.mytype=="tree" || this.obj._h2)) 
		 return;
	 if (this.obj.editStop)
		 this.obj.editStop();
	 if(typeof rowId == "undefined" || this._tSend)
		 return this.sendAllData();
	 if (this._in_progress[rowId])
		 return false;

	 this.messages=[];
	 
	 if (!this.checkBeforeUpdate(rowId)&& this.callEvent("onValidatationError",[rowId,this.messages])) 
		 return false;
	 
	 this._beforeSendData(this._getRowData(rowId),rowId);
 },

 _beforeSendData:function(data,rowId)
 {
	 //alert('_beforeSendData');

	 if (!this.callEvent("onBeforeUpdate",[rowId,this.getState(rowId),data])) 
		 return false;
	 
	 this._sendData(data,rowId);
 },
 serialize:function(data, id)
 {
	 if (typeof id != "undefined")
		 return this.serialize_one(data,"");
	 else
     {
		 var stack = [];
		 var keys = [];
		 
		 for (var key in data)
			 if (data.hasOwnProperty(key))
			 {
				stack.push(this.serialize_one(data[key],key+this.post_delim));
				keys.push(key);
			 };
			 
			 stack.push("ids="+this.escape(keys.join(",")));
			 
			 return stack.join("&");
	 }
 },

 serialize_one:function(data, pref){if (typeof data == "string")return data;var stack = [];for (var key in data)if (data.hasOwnProperty(key))
 stack.push(this.escape((pref||"")+key)+"="+this.escape(data[key]));return stack.join("&");},
 
 _sendData:function(a1,rowId)
 {
	 //alert(a1);

	 //alert(rowId);

	 if (!a1)
		 return;
	 if (!this.callEvent("onBeforeDataSending",rowId?[rowId,this.getState(rowId),a1]:[null, null, a1])) 
		 return false;
	 
	 if (rowId)
		 this._in_progress[rowId]=(new Date()).valueOf();
	 
	 var a2=
			new dtmlXMLLoaderObject(this.afterUpdate,this,true);

	 //alert(a2);

	 //alert('this.serverProcessor '+this.serverProcessor);
	 var a3 = 
			this.serverProcessor+
			(this._user?(getUrlSymbol(this.serverProcessor)+["dhx_user="+
			 this._user,"dhx_version="+this.obj.getUserData(0,"version")].join("&")):"");

	 //alert('a3 '+a3);
	 //alert('this._tMode ' + this._tMode);

	 //alert(' a3+((a3.indexOf("?")!=-1)?"&":"?")+this.serialize(a1,rowId) '+a3+((a3.indexOf("?")!=-1)?"&":"?")+this.serialize(a1,rowId));

	 //this.serialize(a1,rowId)

	 if (this._tMode!="POST")
	 {
		 a2.loadXML(a3+((a3.indexOf("?")!=-1)?"&":"?")+this.serialize(a1,rowId));
	 }else
	 {
		 a2.loadXML(a3,true,this.serialize(a1));
	 }
	
	 this._waitMode++;
 },

 sendAllData:function(){if (!this.updatedRows.length)return;this.messages=[];var valid=true;for (var i=0;i<this.updatedRows.length;i++)valid&=this.checkBeforeUpdate(this.updatedRows[i]);if (!valid && !this.callEvent("onValidatationError",["",this.messages])) return false;if (this._tSend)this._sendData(this._getAllData());else
 for (var i=0;i<this.updatedRows.length;i++)if (!this._in_progress[this.updatedRows[i]]){if (this.is_invalid(this.updatedRows[i])) continue;this._beforeSendData(this._getRowData(this.updatedRows[i]),this.updatedRows[i]);if (this._waitMode && (this.obj.mytype=="tree" || this.obj._h2)) return;}},
 
 
 
 
 
 
 
 
 _getAllData:function(rowId){var out={};var has_one = false;for(var i=0;i<this.updatedRows.length;i++){var id=this.updatedRows[i];if (this._in_progress[id] || this.is_invalid(id)) continue;if (!this.callEvent("onBeforeUpdate",[id,this.getState(id)])) continue;out[id]=this._getRowData(id,id+this.post_delim);has_one = true;this._in_progress[id]=(new Date()).valueOf();};return has_one?out:null;},
 
 
 
 setVerificator:function(ind,verifFunction){this.mandatoryFields[ind] = verifFunction||(function(value){return (value!="");});},
 
 clearVerificator:function(ind){this.mandatoryFields[ind] = false;},
 
 
 
 
 
 findRow:function(pattern){var i=0;for(i=0;i<this.updatedRows.length;i++)if(pattern==this.updatedRows[i])break;return i;},

 
 


 





 
 defineAction:function(name,handler){if (!this._uActions)this._uActions=[];this._uActions[name]=handler;},




 
 afterUpdateCallback:function(sid, tid, action, btag) {var correct=(action!="error" && action!="invalid");if (!correct)this.set_invalid(sid,action);if ((this._uActions)&&(this._uActions[action])&&(!this._uActions[action](btag))) 
 return (delete this._in_progress[sid]);if (this._in_progress[sid]!="wait")this.setUpdated(sid, false);var soid = sid;switch (action) {case "inserted":
 case "insert":
 if (tid != sid){this.obj[this._methods[2]](sid, tid);sid = tid;};break;case "delete":
 case "deleted":
 this.obj.setUserData(sid, this.action_param, "true_deleted");this.obj[this._methods[3]](sid);return this.callEvent("onAfterUpdate", [sid, action, tid, btag]);break;};if (this._in_progress[sid]!="wait"){if (correct)this.obj.setUserData(sid, this.action_param,'');delete this._in_progress[sid];}else {delete this._in_progress[sid];this.setUpdated(tid,true,this.obj.getUserData(sid,this.action_param));};this.callEvent("onAfterUpdate", [sid, action, tid, btag]);},

 
 afterUpdate:function(that,b,c,d,xml){xml.getXMLTopNode("data");if (!xml.xmlDoc.responseXML)return;var atag=xml.doXPath("//data/action");for (var i=0;i<atag.length;i++){var btag=atag[i];var action = btag.getAttribute("type");var sid = btag.getAttribute("sid");var tid = btag.getAttribute("tid");that.afterUpdateCallback(sid,tid,action,btag);};that.finalizeUpdate();},
 finalizeUpdate:function(){if (this._waitMode)this._waitMode--;if ((this.obj.mytype=="tree" || this.obj._h2)&& this.updatedRows.length) 
 this.sendData();this.callEvent("onAfterUpdateFinish",[]);if (!this.updatedRows.length)this.callEvent("onFullSync",[]);},




 
 
 init:function(anObj){this.obj = anObj;if (this.obj._dp_init)this.obj._dp_init(this);},
 
 
 setOnAfterUpdate:function(ev){this.attachEvent("onAfterUpdate",ev);},
 enableDebug:function(mode){},
 setOnBeforeUpdateHandler:function(func){this.attachEvent("onBeforeDataSending",func);},



 
 setAutoUpdate: function(interval, user) {interval = interval || 2000;this._user = user || (new Date()).valueOf();this._need_update = false;this._loader = null;this._update_busy = false;this.attachEvent("onAfterUpdate",function(sid,action,tid,xml_node){this.afterAutoUpdate(sid, action, tid, xml_node);});this.attachEvent("onFullSync",function(){this.fullSync();});var self = this;window.setInterval(function(){self.loadUpdate();}, interval);},


 
 afterAutoUpdate: function(sid, action, tid, xml_node) {if (action == 'collision'){this._need_update = true;return false;}else {return true;}},


 
 fullSync: function() {if (this._need_update == true){this._need_update = false;this.loadUpdate();};return true;},


 
 getUpdates: function(url,callback)
 {
	 if (this._update_busy)
		 return false;
	 else
		 this._update_busy = true; 
		 this._loader = this._loader || new dtmlXMLLoaderObject(true);
		 this._loader.async=true;
		 this._loader.waitCall=callback;
		 this._loader.loadXML(url);
 },


 
 _v: function(node)
 {
	 if (node.firstChild)
		 return node.firstChild.nodeValue;
	 return "";
  },

 _a: function(arr) 
  {
	 var res = [];
	 
	 for (var i=0;i < arr.length;i++)
	 {
		 res[i]=this._v(arr[i]);
	 };
	 
	 return res;
   },


 
 loadUpdate: function(){var self = this;var version = this.obj.getUserData(0,"version");var url = this.serverProcessor+getUrlSymbol(this.serverProcessor)+["dhx_user="+this._user,"dhx_version="+version].join("&");url = url.replace("editing=true&","");this.getUpdates(url, function(){var vers = self._loader.doXPath("//userdata");self.obj.setUserData(0,"version",self._v(vers[0]));var upds = self._loader.doXPath("//update");if (upds.length){self._silent_mode = true;for (var i=0;i<upds.length;i++){var status = upds[i].getAttribute('status');var id = upds[i].getAttribute('id');var parent = upds[i].getAttribute('parent');switch (status) {case 'inserted':
 self.callEvent("insertCallback",[upds[i], id, parent]);break;case 'updated':
 self.callEvent("updateCallback",[upds[i], id, parent]);break;case 'deleted':
 self.callEvent("deleteCallback",[upds[i], id, parent]);break;}};self._silent_mode = false;};self._update_busy = false;self = null;});}};
 //(c)dhtmlx ltd. www.dhtmlx.com//v.2.6 build 100722
 /*
Copyright DHTMLX LTD. http://www.dhtmlx.com
To use this component please contact sales@dhtmlx.com to obtain license
*/
